
/*
#include <iostream>
#include "Memory/MemoryWrapper.h"
#include "Memory Manager/Memory Tables/MemoryTable.h"
#include "Memory Manager/SerialMemoryManager.h"
#include "Packets/PubPkt.h"
#include "Common/Consts.h"
#include "Test/Producer.h"
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include "Subscription Manager/SienaInterface.h"
#include "Interface/OutputListener.h"
#include "Interface/StorexEngine.h"
#include "Interface/Box.h"
*/
#include "Test/RunEval.h"
#include "Server/StorexServer.h"
#include <stdlib.h>
#include <stdio.h>
/*
#include <boost/random/normal_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/bernoulli_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>
*/

using namespace std;
using namespace storex_testing;


void usage() {
	cout << "Usage: sToRex [-server [<port>] | -eval]" << endl;
	cout << "-server   -> run a sToRex server listening for clients on the specified port (default: 9999)" << endl;
	cout << "-eval     -> run performance evaluation of the sToRex engine" << endl;
	exit (-1);
}
/*
int main(int argc, char* argv[]) {

	float p = 0.8;
	boost::mt19937 igen(0);
	boost::variate_generator<boost::mt19937, boost::bernoulli_distribution<> > gen(igen, boost::bernoulli_distribution<>(p));

	for (int i=0; i<15; i++){
		cout << gen() << endl;
	}
}
*/



int main(int argc, char* argv[]) {
	if (argc==2 && strcmp(argv[1], "-eval")==0) runEval();
	else if (argc>=2 && argc<=3 && strcmp(argv[1], "-server")==0) {
		int port = 9999;
		if (argc==3) port = atoi(argv[2]);
		StorexServer server(port, 1);
		server.run();
	} else usage();
	return 0;
}



// -------------------------------------------------------------------------------------------------------------------------------------------------------- //










/*

typedef enum {
	TEMP = 1,
	WIND = 2,
//	RAIN = 3,
//	SNOW = 4
} EventType;

class MyListener : public OutputListener {

public:

	MyListener(){ }

	virtual ~MyListener() {}

	void handleOutput(Outbox &outbox){
		cout << endl;
		cout << "**************************** OUTBOX ****************************" << endl;
		cout << "Clients:  ";
		if (!outbox.clients.empty()){
			for (std::set<int>::iterator it = outbox.clients.begin(); it != outbox.clients.end(); it++){
				cout << *it << " ";
			}
		} else {
			cout << "-";
		}
		cout << endl;
		cout << "Messages: ";
		if (!outbox.pkts.empty()){
			cout << endl;
			for (std::set<PubPkt*>::iterator it2 = outbox.pkts.begin(); it2 != outbox.pkts.end(); it2++){
				PubPkt* refPkt = *it2;
				cout << "\t  " << test::toString(refPkt) << endl;
			}
		} else{
			cout << "-" << endl;
		}
		cout << "****************************************************************" << endl << endl;
		return;
	}
};


int main() {


	int max = 100000;
	float lambda = 1;
	float a = 0.999;
	float quantile = (1/lambda)*log(1/(1-a));
	int scale = max/quantile;
	boost::mt19937 igen;
	boost::variate_generator<boost::mt19937, boost::exponential_distribution<> > gen(igen, boost::exponential_distribution<>(lambda));
	for (int i=0; i<100; i++){
		int intero = (gen() * scale);
		std::cout << intero << std::endl;
	}
*/

/*
	// *** Istanzio STOREX *** //

	MyListener *listener = new MyListener();
	ConfigHandler *configHandler = new ConfigHandler();
	//configHandler->setDefaultOCM();
	configHandler->setDefaultSienaFF();
	//configHandler->setSubsThreshold(40);
	configHandler->setMemoryTableType(ALLOCATION);
	configHandler->setStorageType(CACHE);
	configHandler->setIndexingType(SIMPLE);
	StorexEngine *storexEngine = new StorexEngine(configHandler, listener);


	for (int i=0; i<300; i++) {
		int randomGeneral = rand()%3;
		if ( randomGeneral == 0 || randomGeneral == 1 ){

			// *** Invio Messaggio ***  //
			int randomType = rand()%2;

			if (randomType == 0){
				Attribute attributes[2];
				int choice = rand()%3;
				if (choice == 0){
					attributes[0] = test::produceStringAttribute("location", "Milano");
				} else if (choice==1){
					attributes[0] = test::produceStringAttribute("location", "Torino");
				} else if (choice==2){
					attributes[0] = test::produceStringAttribute("location", "Napoli");
				}
				attributes[1] = test::produceIntAttribute("value", (rand()%15+15));
				PubPkt* eventPkt = new PubPkt(TEMP, attributes, 2);
				eventPkt->setCurrentTime();
				cout << "Created message: " << test::toString(eventPkt) << " with timestamp: " << eventPkt->getTimeStamp().getTimeVal() << endl;
				cout << "Sending message..." << endl;
				storexEngine->processPubPkt(eventPkt);
			} else {
				Attribute attributes[2];
				int choice = rand()%3;
				if (choice == 0){
					attributes[0] = test::produceStringAttribute("location", "Genova");
				} else if (choice==1){
					attributes[0] = test::produceStringAttribute("location", "Trieste");
				} else if (choice==2){
					attributes[0] = test::produceStringAttribute("location", "Palermo");
				}
				attributes[1] = test::produceIntAttribute("speed", (rand()%100));
				PubPkt* eventPkt = new PubPkt(WIND, attributes, 2);
				eventPkt->setCurrentTime();
				cout << "Created message: " << test::toString(eventPkt) << " with timestamp: " << eventPkt->getTimeStamp().getTimeVal() << endl;
				cout << "Sending message..." << endl;
				storexEngine->processPubPkt(eventPkt);
			}

		} else {

			// *** Invio Sottoscrizione *** //
			int randomType = rand()%2;

			if (randomType == 0){
				Constraint constraint[2];
				int choice = rand()%3;
				if (choice == 0){
					constraint[0] = test::produceStringConstraint("location", EQ, "Milano");
				} else if (choice==1){
					constraint[0] = test::produceStringConstraint("location", EQ, "Torino");
				} else if (choice==2){
					constraint[0] = test::produceStringConstraint("location", EQ, "Napoli");
				}
				constraint[1] = test::produceIntConstraint("value", (Op)(rand()%3), (rand()%15+15));
				BackSubPkt* subPkt = new BackSubPkt(TEMP, constraint, 2, ((rand()%19)+1)*1000, (OccurrenceType)(rand()%2));
				subPkt->setCurrentTime();
				cout << "Created subscription: " << test::toString(subPkt) << " with timestamp: " << subPkt->getTimeStamp().getTimeVal() << endl;
				int clientId = (rand()%5)+120;
				Inbox *inbox = new Inbox(clientId, subPkt);
				cout << "Sending subscription..." << endl;
				storexEngine->processSubPkt(inbox);
			} else {
				Constraint constraint[2];
				int choice = rand()%3;
				if (choice == 0){
					constraint[0] = test::produceStringConstraint("location", EQ, "Genova");
				} else if (choice==1){
					constraint[0] = test::produceStringConstraint("location", EQ, "Trieste");
				} else if (choice==2){
					constraint[0] = test::produceStringConstraint("location", EQ, "Palermo");
				}
				constraint[1] = test::produceIntConstraint("speed", (Op)(rand()%3), (rand()%100));
				BackSubPkt* subPkt = new BackSubPkt(WIND, constraint, 2, ((rand()%29)+1)*1000, (OccurrenceType)(rand()%2));
				subPkt->setCurrentTime();
				cout << "Created subscription: " << test::toString(subPkt) << " with timestamp: " << subPkt->getTimeStamp().getTimeVal() << endl;
				int clientId = (rand()%5)+120;
				Inbox *inbox = new Inbox(clientId, subPkt);
				cout << "Sending subscription..." << endl;
				storexEngine->processSubPkt(inbox);
			}

		}
		sleep(1);
	}

	delete listener;
	delete configHandler;
	delete storexEngine;

	return 0;
}

*/
